// 迭代器模式允许你对一个序列的项进行某些处理。
// 迭代器（iterator）负责遍历序列中的每一项和决定序列何时结束的逻辑。
// 当使用迭代器时，我们无需重新实现这些逻辑。
// 在 Rust 中，迭代器是 惰性的（lazy），这意味着在调用方法使用迭代器之前它都不会有效果

/*

pub trait Iterator {
    type Item; //定义返回值类型
    fn next(&mut self) -> Option<Self::Item>; //next 一次返回迭代器中的一个项，封装在 Some 中，当迭代器结束时，它返回 None
    // 此处省略了方法的默认实现
}
*/
#[cfg(test)]
mod iterator_test {
    use crate::basex::fun::iterator::Shoe;

    #[test]
    fn iterator_base() {
        let v1 = vec![1, 2, 3];
        let v1_iter = v1.iter();
        for val in v1_iter {
            println!("Got: {}", val);
        }
        let mut v1_iter = v1.iter(); //在迭代器上调用 next 方法改变了迭代器中用来记录序列位置的状态
        // 从 next 调用中得到的值是 vector 的不可变引用。iter 方法生成一个不可变引用的迭代器
        println!("Got: {:?}", v1_iter.next());

        // .into_iter -->获取所有权并返回拥有所有权的迭代器
        // .iter_mut  -->希望迭代可变引用
    }

    // 消费迭代器的方法
    #[test]
    fn iterator_next() {
        // next 方法的方法被称为 消费适配器（consuming adaptors）
        let v1 = vec![1, 2, 3];
        let v1_iter = v1.iter();
        let total: i32 = v1_iter.sum(); //这个方法获取迭代器的所有权并反复调用 next 来遍历迭代器，因而会消费迭代器。
        // 调用 sum 之后不再允许使用 v1_iter 因为调用 sum 时它会获取迭代器的所有权。
        println!("{}", total)
    }

    // 允许将当前迭代器变为不同类型的迭代器,不过因为所有的迭代器都是惰性的，必须调用一个消费适配器方法以便获取迭代器适配器调用的结果。
    #[test]
    fn iterator_adaptors() {
        let v1: Vec<i32> = vec![1, 2, 3];
        let map = v1.iter().map(|x| x + 1);
        println!("{:?}", map);

        let map: Vec<_> = v1.iter().map(|x| x + 1).collect(); //方法消费迭代器并将结果收集到一个数据结构中。
        println!("{:?}", map);
    }

    // 闭包来筛选
    fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
        shoes.into_iter().filter(|s| s.size == shoe_size).collect()
    }

    #[test]
    fn filters_by_size() {
        let shoes = vec![
            Shoe {
                size: 10,
                style: String::from("sneaker"),
            },
            Shoe {
                size: 13,
                style: String::from("sandal"),
            },
            Shoe {
                size: 10,
                style: String::from("boot"),
            },
        ];

        let in_my_size = shoes_in_my_size(shoes, 10);

        assert_eq!(
            in_my_size,
            vec![
                Shoe {
                    size: 10,
                    style: String::from("sneaker")
                },
                Shoe {
                    size: 10,
                    style: String::from("boot")
                },
            ]
        );
    }
}

#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

//===============

#[cfg(test)]
mod iterator_custom {
    #[derive(PartialEq, Debug)]
    struct Counter {
        count: u32,
    }

    impl Counter {
        fn new() -> Counter {
            Counter { count: 0 }
        }
    }

    impl Iterator for Counter {
        type Item = u32;
        fn next(&mut self) -> Option<Self::Item> {
            self.count += 1;
            if self.count < 6 {
                Some(self.count)
            } else {
                None
            }
        }
    }

    #[test]
    fn counter_iterator() {
        let mut counter = Counter::new();
        for x in 0..=7 {
            println!("{:?}", counter.next());
        }
    }

    #[test]
    fn counter_iterator_method() {
        let sum: u32 = Counter::new()
            .zip(Counter::new().skip(1))
            .map(|(a, b)| a * b)
            .filter(|x| x % 3 == 0)
            .sum();
        // 注意 zip 只产生四对值；理论上第五对值 (5, None) 从未被产生，因为 zip 在任一输入迭代器返回 None 时也返回 None。
        assert_eq!(18, sum);

        println!("{:?}", Counter::new().skip(1)); //Skip { iter: Counter { count: 0 }, n: 1 } //跳过 iter 的 n 元素的迭代器。
        println!("{:?}", Counter::new().zip(Counter::new().skip(1)));
        println!(
            "{:?}",
            Counter::new()
                .zip(Counter::new().skip(1))
                .map(|(a, b)| a * b)
                .filter(|x| x % 3 == 0)
        );

        // 0 1   skip
        // 1 2   filter
        // 2 * 3  +  3 * 4
        // 4 5   filter
        // 5 None

        // self.count < 6  next限制为 =5
    }

    #[test]
    fn counter_iterator_match() {
        let mut counter = Counter::new();
        // 使用 Iterator trait 代替索引
        // println!("{}", counter[1]); //没有实现 index
        println!(
            "{}",
            match counter.next() {
                Some(x) => x,
                None => 0,
            }
        );
        println!("{}", counter.next().unwrap_or_else(|| 0));
    }
}

/*
迭代器是 Rust 的 零成本抽象（zero-cost abstractions）之一，它意味着抽象并不会引入运行时开销，
它与本贾尼·斯特劳斯特卢普（C++ 的设计和实现者）在 “Foundations of C++”（2012） 中所定义的 零开销（zero-overhead）如出一辙
    从整体来说，C++ 的实现遵循了零开销原则：你不需要的，无需为他们买单。更有甚者的是：你需要的时候，也不可能找到其他更好的代码了。


*/

/*


遍历 coefficients 的值完全用不到循环：Rust 知道这里会迭代 12 次，所以它“展开”（unroll）了循环。展开是一种移除循环控制代码的开销并替换为每个迭代中的重复代码的优化。

let buffer: &mut [i32];
let coefficients: [i64; 12];
let qlp_shift: i16;

for i in 12..buffer.len() {
    let prediction = coefficients.iter()
                                 .zip(&buffer[i - 12..i])
                                 .map(|(&c, &s)| c * s as i64)
                                 .sum::<i64>() >> qlp_shift;
    let delta = buffer[i];
    buffer[i] = prediction as i32 + delta;
}


*/
